﻿//Copyright 2008 Kristian Gundry And Rune Juhl-Petersen
//This file is part of Plain.

//Plain is free software: you can redistribute it and/or modify
//it under the terms of the GNU Lesser General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//any later version.

//Plain is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU Lesser General Public License for more details.

//You should have received a copy of the GNU Lesser General Public License
//along with Plain.  If not, see <http://www.gnu.org/licenses/>.using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System;

namespace Plain.DuckTyping {
    public static class MethodExtensions {
        public static object CallMethod(this object o, string name) {
            return o.GetType().GetMethod(name).Invoke(o, null);
        }
        public static object CallMethod(this object o, string name, params object[] parameters) {
			Type[] types = parameters.Select(x=>x.GetType()).ToArray();
            return o.GetType().GetMethod(name,types).Invoke(o, parameters);
        }
        public static T CallMethod<T>(this object o, string name) {
            return (T)o.GetType().GetMethod(name).Invoke(o, null);
        }
        public static T CallMethod<T>(this object o, string name,params object[] parameters) {
			Type[] types = parameters.Select(x=>x.GetType()).ToArray();
            return (T)o.GetType().GetMethod(name,types).Invoke(o, parameters);
        }
        public static Invoker GetMethod(this object o, string name,params Type[] types){
            MethodInfo g = null;
            foreach (MethodInfo m in o.GetType().GetMethods()) {
                if (m.Name == name && m.IsGenericMethod) {
                    g = m.MakeGenericMethod(types);
                    break;
                }
            }
            return new Invoker(g, o);
        }
        public static Invoker<T> GetMethod<T>(this object o, string name, params Type[] types) {
            MethodInfo g = null;
            foreach (MethodInfo m in o.GetType().GetMethods()) {
                if (m.Name == name && m.IsGenericMethod) {
                    g = m.MakeGenericMethod(types);
                    break;
                }
            }
            return new Invoker<T>(g, o);
        
        }

    }
    public class Invoker {
        private MethodInfo method;
        private object o;
        public Invoker(MethodInfo method,object o){
            this.method = method;
            this.o = o;
        }
        public void Call(params object[] parameters) {
            method.Invoke(o, parameters);
        }
        public void Call() {
            method.Invoke(o, null);
        }
     
    }
    public class Invoker<T> {
        private MethodInfo method;
        private object o;
        public Invoker(MethodInfo method, object o) {
            this.method = method;
            this.o = o;
        }
        public T Call(params object[] parameters) {
            return (T)method.Invoke(o, parameters);
        }
        public T Call() {
            return (T)method.Invoke(o,null);
        }
       
    }
}
